# -*- coding: utf-8 -*-
"""
Created on Wed Mar 31 14:42:03 2021

@author: Hu Yue
@email: hhhuyue@gmail.com

Note:
"""
import pandas as pd
import threading
import time

# 读取数据


option_price = pd.read_feather("./data/optionprice.feather")
stock_price = pd.read_feather("./data/stockprice.feather")


#%% calculate the time2mat 8.6s

option_price['Date'] = pd.to_datetime(option_price.Date,format="%Y-%m-%d")
option_price['Expiration'] = pd.to_datetime(option_price.Expiration,format="%Y-%m-%d")
option_price.loc[:,'time2mat'] =(pd.eval("option_price.Expiration-option_price.Date")).dt.days
option_price.loc[:,'weekday']=option_price.Expiration.dt.weekday
#%% 
# z这一段运行只需要0.5s
import numpy as np
n = 7 #剩余到期日
weekday= 4 # 只看周五到期的期权

stocks = stock_price['SecurityID'][~(stock_price['SecurityID'].duplicated())] #运行极快，可忽略不计
option_price_7 = option_price[(option_price['time2mat']==n)] # &(option_price['weekday']==weekday)
# 去掉delta大于0.95和小于0.05的
option_price_7 = option_price_7[(option_price_7['Delta']<=0.55) & (option_price_7['Delta']>=0.05) ]
# 去掉交易量为0的期权
option_price_7 = option_price_7[option_price_7['Volume']>0]
# 取每周最后一天的数据
option_price.loc['year'] = option_price['Date'].dt.year
option_price.loc['week_num'] = option_price['Date'].dt.week

option_price = option_price.groupby(['OptionID','year','week_num']).tail(1)  #取的就是最后一条数据


#%%
# 数据处理 用自己计算的delta值和期权价格



#%%
# =============================================================================
# 
# begin_time = time.time()
# stock=106445
# options = option_price_7[option_price_7['SecurityID']==stock]
# end_time =time.time()
# print("程序运行耗费时间为：{}s".format(end_time-begin_time))
# =============================================================================
#%%
import traceback
import logging
logging.basicConfig(filename='log.log')
import warnings
warnings.filterwarnings("ignore")

def get_hedged_retDT1(stock_info,option_info,params,filepath):
    
    start_date = params['start_date']
    end_date = params['end_date']

    
    if len(stock_info) ==0 or len(option_info) ==0:
       logging.error("期权{}或证券{}没有相应的数据啦！".format(params['OptionID'],params['SecurityID']))
       return {}
    
    stock_info.set_index(['Date'],inplace=True,drop=False)
    option_info.set_index(['Date'],inplace=True,drop=False)
    
    option_info.loc[:,'spread'] = pd.eval('option_info.BestOffer-option_info.BestBid')
    option_info['ImpliedVolatility'][option_info['ImpliedVolatility'] <-99] =np.nan
    option_info.loc[:,'midprice']  =pd.eval('option_info.BestOffer+option_info.BestBid') /2
    option_info['Strike'] = option_info.Strike/1000
    
    #option_info.loc[:,'ImpliedVolatility'] = option_info.loc[:,'ImpliedVolatility'].fillna(method='ffill')
    
    start_price = stock_info.loc[start_date,'Price']
    
    sigma =option_info.loc[start_date,'ImpliedVolatility']
    delta = option_info.loc[start_date,'Delta']
    time2mat = option_info.loc[start_date,'time2mat']
    cptype = option_info.loc[start_date,'CallPut']
    K = option_info.loc[start_date,'Strike']
    start_cost = option_info.loc[start_date,'midprice'] 
    end_price = stock_info.loc[end_date,'Price']
    endcost1 =  option_info.loc[end_date,'midprice']
    
    rate = 0.04/365/100
        
    # 计算每天的对冲成本和总的对冲成本
    hedge_info = stock_info.join(option_info.drop(['Date','SecurityID'],axis=1))
         
    hedge_info.sort_index(inplace=True)
    hedge_info.loc[:,'sign'] = (hedge_info['CallPut']=='C')*1
    hedge_info.loc[:,'sign_up'] = (hedge_info['Price']>hedge_info['Strike'])*1
    hedge_info.loc[:,'sign_down'] = (hedge_info['Price']<hedge_info['Strike'])*1
    
    hedge_info['Delta'][hedge_info['Delta'] <-99] =pd.eval('hedge_info.sign*(1-hedge_info.sign_down)+(1-hedge_info.sign)*(hedge_info.sign_up-1)') 
    
# =============================================================================
#     hedge_info['shares_bought'] = hedge_info['Delta'] - hedge_info['Delta'].shift(1).fillna(0)
#     hedge_info['PnL'] =  hedge_info['shares_bought'] *  hedge_info['Price']
# =============================================================================
    hedge_info['diff_price'] = hedge_info['Price'].shift(-1)-hedge_info['Price']
    hedge_info['PnL']= pd.eval('hedge_info.diff_price*hedge_info.Delta')*(-1)
    hedge_info['days_diff'] = hedge_info['time2mat'].shift(-1) -hedge_info['time2mat']
    hedge_info['interest'] = (-start_cost + hedge_info['Delta']*hedge_info['Price']) * rate*hedge_info['days_diff']
    
    # 记录当天的损益
    hedge_info['Date'] = hedge_info['Date'].apply(lambda x: x.strftime("%Y-%m-%d"))
    hedge_info['stock_gain'] = -(hedge_info['Price'].shift(-1) - hedge_info['Price'])*hedge_info['Delta']
    hedge_info['option_gain'] = hedge_info['midprice'].shift(-1) - hedge_info['midprice']
    hedge_info['total_gain'] = hedge_info['stock_gain'] + hedge_info['option_gain']
    hedge_info = hedge_info.round({"stock_gain":5,"option_gain":5,"total_gain":5})
    hedgeret = hedge_info['PnL'].sum()
    interest2 = hedge_info['interest'].sum()
    
    daily_pnl = np.array(hedge_info[['Date','stock_gain','option_gain','total_gain']]).tolist()
    
    if cptype == "Call":

        endcost2 = max(end_price-K,0)
    else:

        endcost2 = max(K-end_price,0)
           
    mat = (option_info.loc[end_date,'time2mat']>0)*1  
    endcost = mat*endcost2 +(1-mat)*endcost1
    
    PnL = start_cost - endcost - hedgeret - 0.35*option_info.loc[start_date,'spread'] -interest2 
    ret ={
        "start_cost":start_cost,
        "startspred":option_info.loc[start_date,'spread'],
        "startvega":option_info.loc[start_date,'Vega'],
        "startprice":start_price,
        "endcost1":endcost1,
        "endcost2":endcost2,
        "K":K,
        "endprice":end_price,
        "hedgeret":hedgeret,
        "mat":mat,
        "endspred":option_info.loc[end_date,'spread'],
        "SecurityID":params['SecurityID'],
        "lastday": option_info.loc[start_date,'Expiration'].strftime("%Y-%m-%d"),
        "time2mat":time2mat,
        "startdate":start_date.strftime("%Y-%m-%d"),
        "end_date":end_date.strftime("%Y-%m-%d"),
        "OptionID":params['OptionID'],
        "VOL":option_info.loc[start_date,'Volume'],
        "IV":sigma,
        "Gamma":option_info.loc[start_date,'Gamma'],
        "Delta":delta,
        "endcost":endcost,
        "PnL":PnL,
        "cptype":cptype,
        "interest2":interest2,
        "daily_pnl":daily_pnl
        }
# =============================================================================
#     if(np.abs(PnL)>2):
#         print("%d，%d的Pnl为%f"%(SecurityID,OptionID,PnL))
#         print(hedge_info[['Date','Delta','shares_bought','PnL']])
# =============================================================================

    if ret:
       with open(filepath,"a") as f:
           f.write(json.dumps(ret,cls=MyEncoder))
           f.write("\n")
    return ret

import json
class MyEncoder(json.JSONEncoder):
   def default(self,obj):
       if isinstance(obj,np.integer):
           return int(obj)
       elif isinstance(obj, np.floating):
           return float(obj)
       elif isinstance(obj,np.ndarray):
           return obj.tolist()
       else:
           return super(MyEncoder,self).default(obj)
       
import os

 # 运行只需要1s多
for stock in stocks:
    begin_time = time.time()
    
    print("the SecurityID is :{}".format(stock))

    options = option_price_7[option_price_7['SecurityID']==stock]
    options_ = option_price[(option_price['SecurityID']==stock)]
    
    prices = stock_price[['Date','SecurityID','Price']][stock_price['SecurityID']==stock]
    prices.loc[:,'Date'] = pd.to_datetime(prices.Date,format="%Y-%m-%d")
    #specific_stock_price = specific_stock_price[(specific_stock_price['Date']<=end_date)&(specific_stock_price['Date']>=start_date)]
    #specific_stock_price.set_index(['Date'],inplace=True,drop=False)
    
    #创建文件夹
    file_path = "result_thread/%d/"%stock
    if not os.path.exists(file_path):
        os.makedirs(file_path)
        
    file_name='%d_%d.json'%(stock,n)
     
    days =  options[['Date','Expiration']][~(options['Date'].duplicated())]
    for _,day in days.iterrows():
        
        start_date = pd.to_datetime(day['Date'])
        end_date = pd.to_datetime(day['Expiration'])
        stock_info = prices[(prices['Date']<=end_date)&(prices['Date']>=start_date)]
        if end_date in set(stock_info.Date):
           
            options_info = options_[(options_['Date']<=end_date)&(options_['Expiration']>=start_date)]
            
            option_day = options[options['Expiration']==end_date]
            print("\t","the Date is {}".format(end_date))
            threads = []
            for idx,row in option_day.iterrows():
                
                option = row['OptionID']
                print("\t\t","the option is {}".format(option))
                option_info = options_info[options_info['OptionID']==option]
                params = {'start_date':start_date,
                          'end_date':end_date,
                          'SecurityID':stock,
                          'OptionID':option}
      
                #hedge_info = get_hedged_retDT1(stock_info,option_info,params)    ]
                filepath = file_path+file_name
                t = threading.Thread(target=get_hedged_retDT1,args=(stock_info,option_info,params,filepath))
                threads.append(t)
                
            for th in threads :
                th.start()
               
        
    
    end_time =time.time()
    print("程序运行耗费时间为：{}s".format(end_time-begin_time))

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    